package com.hzlj.position.locate.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.fz.common.base.core.DistanceUtils;
import com.fz.common.base.core.date.DateUtils;
import com.fz.common.base.dto.PageParamDTO;
import com.fz.common.base.dto.QueryPageResultDTO;
import com.fz.common.dict.annotation.DictConvert;
import com.google.common.collect.Maps;
import com.hzlj.common.message.common.dto.message.MessageNoticeUserDTO;
import com.hzlj.common.message.common.util.MessageRestUtil;
import com.hzlj.position.config.common.dto.common.PositionCommonDTO;
import com.hzlj.position.config.config.PositionConfig;
import com.hzlj.position.config.service.NoticeConfigService;
import com.hzlj.position.locate.common.dto.abnNightActivity.AbnNightActivityListDTO;
import com.hzlj.position.locate.common.dto.abnNightActivity.AbnNightActivityQueryParamDTO;
import com.hzlj.position.locate.common.dto.abnNightActivityJzry.AbnNightActivityJzryAddDTO;
import com.hzlj.position.locate.common.model.AbnNightActivity;
import com.hzlj.position.locate.dao.AbnNightActivityDao;
import com.hzlj.position.locate.service.AbnNightActivityJzryService;
import com.hzlj.position.locate.service.AbnNightActivityService;
import com.hzlj.position.locate.service.PositionService;
import com.hzlj.sqjz.config.common.enums.JgLscj;
import com.hzlj.sqjz.system.service.JgService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.hzlj.position.config.config.IdConfig.POSITION_ID_GEN;

/**
 * 定位分析-夜间活动表(AbnNightActivity)表服务接口
 *
 * @author lifh
 * @date 2023-03-28 18:38:38
 */
@Slf4j
@Service
public class AbnNightActivityServiceImpl implements AbnNightActivityService {
    /**
     * 最近一条记录距离
     */
    private final static Integer DISTANCE_FROM_LATEST = 2000;
    @Resource
    private AbnNightActivityDao abnNightActivityDao;
    @Resource
    private AbnNightActivityJzryService abnNightActivityJzryService;
    @Resource
    private PositionService positionService;
    @Resource
    private JgService jgService;
    @Resource
    private NoticeConfigService noticeConfigService;
    @Resource
    private PositionConfig positionConfig;

    /**
     * 夜间活动分析
     * 从0-6点开始，与最近一次定位的距离相差2KM
     */
    @Override
    public void abn() {
        //时间
        Date startDay = positionConfig.getAbn().nightActivityYesterday() ? DateUtils.yesterday() : DateUtils.now();
        Date endDay = DateUtils.now();
        Date startTime = DateUtils.parseDate(startDay, "yyyy-MM-dd " + positionConfig.getAbn().getNightActivityStartTime());
        Date endTime = DateUtils.parseDate(endDay, "yyyy-MM-dd " + positionConfig.getAbn().getNightActivityEndTime());
        //
        List<String> jgCodes = jgService.jgCodesByLscj(null, JgLscj.CITY.getCode(), null);
        log.info("获取机构数[夜间活动]:size={}", jgCodes.size());
        for (String jgCode : jgCodes) {
            List<PositionCommonDTO> positions = positionService.listPosition4Abn(jgCode, startTime, endTime);
            log.info("获取位置数量[夜间活动]:size={},jgCode={},startTime={},endTime={}", positions.size(), jgCode, startTime, endTime);
            if (ObjectUtil.isEmpty(positions)) {
                continue;
            }
            Map<String, PositionCommonDTO> latestPositions = Maps.newHashMap();

            //过滤
            Map<String, List<AbnNightActivityJzryAddDTO>> filterPositions = positions.stream()
                    .map(e -> {
                        //最近的一条
                        PositionCommonDTO latest = latestPositions.get(e.getJzId());
                        latestPositions.put(e.getJzId(), e);
                        if (latest == null) {
                            return null;
                        }
                        double distance = DistanceUtils
                                .amapDistance(Double.parseDouble(latest.getLongitude()), Double.parseDouble(latest.getLatitude()), Double.parseDouble(e.getLongitude()), Double.parseDouble(e.getLatitude()));
                        if (distance <= DISTANCE_FROM_LATEST) {
                            return null;
                        }
                        AbnNightActivityJzryAddDTO position = BeanUtil.copyProperties(e, AbnNightActivityJzryAddDTO.class);
                        position.setDistance(new BigDecimal(distance));
                        return position;
                    }).filter(Objects::nonNull).collect(Collectors.groupingBy(AbnNightActivityJzryAddDTO::getJzId));

            for (Map.Entry<String, List<AbnNightActivityJzryAddDTO>> entry : filterPositions.entrySet()) {
                this.saveAbnNightActivities(
                        entry.getKey(),
                        startTime,
                        endTime,
                        entry.getValue());
            }
        }
    }

    private void saveAbnNightActivities(String jzId,
                                        Date startTime,
                                        Date endTime,
                                        List<AbnNightActivityJzryAddDTO> dtos) {
        if (ObjectUtil.isEmpty(dtos)) {
            return;
        }
        AbnNightActivity abn = new AbnNightActivity();
        abn.setId(POSITION_ID_GEN.nextIdStr());
        abn.setJzId(jzId);
        abn.setStartTime(startTime);
        abn.setEndTime(endTime);
        abn.setPositionsNum(dtos.size());
        abn.setCreateTime(new Date());

        //新增数据
        this.abnNightActivityDao.save(abn);

        //新增明细
        this.abnNightActivityJzryService.saveAbnNightActivityJzry(abn.getId(), dtos);

        //发送通知
        this.noticeGzry(dtos.get(0));
    }


    /**
     * 查询列表：分页
     *
     * @param dto  查询条件
     * @param page 分页信息
     * @return 对象列表
     */
    @Override
    @DictConvert
    public QueryPageResultDTO<AbnNightActivityListDTO> pageAbnNightActivity(AbnNightActivityQueryParamDTO dto, PageParamDTO page) {
        return this.abnNightActivityDao.pageAbnNightActivity(dto, page);
    }


    private void noticeGzry(AbnNightActivityJzryAddDTO jzJbxx) {
        Map<String, Object> params = Maps.newHashMap();
        params.put("jzryXm", jzJbxx.getXm());
        params.put("abnTypeText", "夜间活动");
        params.put("positionTime", DateUtil.formatDate(jzJbxx.getPositionTime()));
        MessageRestUtil.noticeQueryUsers(
                "abn-night-activity-gzry",
                jzJbxx.getId(),
                params,
                MessageNoticeUserDTO.of(true, jzJbxx.getJgCode(), noticeConfigService.defaultMessageNoticeAuths(jzJbxx.getJgCode()))
        );
    }
}
